home *** CD-ROM | disk | FTP | other *** search
/ Aminet 44 / Aminet 44 (2001)(GTI - Schatztruhe)[!][Aug 2001].iso / Aminet / dev / gui / gtlayout.lha / Source / LTP_TextEdit.c < prev    next >
C/C++ Source or Header  |  1999-01-03  |  44KB  |  2,107 lines

  1. /*
  2. **    GadTools layout toolkit
  3. **
  4. **    Copyright © 1993-1999 by Olaf `Olsen' Barthel
  5. **        Freely distributable.
  6. **
  7. **    :ts=4
  8. */
  9.  
  10. #ifndef _GTLAYOUT_GLOBAL_H
  11. #include "gtlayout_global.h"
  12. #endif
  13.  
  14. /******************************************************************************/
  15.  
  16. #ifdef DO_TEXTEDIT_KIND    /* Support code */
  17.  
  18. /******************************************************************************/
  19.  
  20. #include <graphics/gfxmacros.h>
  21. #include <exec/memory.h>
  22.  
  23. #include <clib/layers_protos.h>
  24. #include <clib/alib_protos.h>    /* For Coerce/Do/DoSuperMethod */
  25.  
  26. #include <pragmas/layers_pragmas.h>
  27.  
  28. /******************************************************************************/
  29.  
  30. #define VISIBLE (0)
  31.  
  32. /******************************************************************************/
  33.  
  34. #define GRANULARITY 100
  35.  
  36. /******************************************************************************/
  37.  
  38. struct TextEditContext
  39. {
  40.     STRPTR                tec_String;
  41.     LONG                tec_StringTotalSize;
  42.     LONG                tec_StringUsedSize;
  43.  
  44.     STRPTR                tec_BackupString;
  45.     LONG                tec_BackupStringSize;
  46.  
  47.     struct RastPort *    tec_RastPort;
  48.  
  49.     UWORD                tec_TextPen;
  50.     UWORD                tec_BackPen;
  51.     UWORD                tec_ShadowPen;
  52.  
  53.     UWORD                tec_ActiveTextPen;
  54.     UWORD                tec_ActiveBackPen;
  55.     UWORD                tec_InactiveTextPen;
  56.     UWORD                tec_InactiveBackPen;
  57.  
  58.     BOOL                tec_IsActive;
  59.     BOOL                tec_IsDrawable;
  60.  
  61.     BOOL                tec_BufferChanged;
  62.     BOOL                tec_MustRedraw;
  63.     LONG                tec_RedrawStartLine;
  64.     LONG                tec_RedrawStopLine;
  65.     ULONG                tec_CursorVisible;
  66.  
  67.     STRPTR                tec_LinePointer;
  68.     LONG                tec_LineIndex;
  69.  
  70.     LONG                tec_MaxPixels;
  71.     LONG                tec_MaxColumns;
  72.     LONG                tec_MaxLines;
  73.  
  74.     LONG                tec_FirstLine;
  75.     LONG                tec_FirstPixel;
  76.  
  77.     WORD                tec_Left;
  78.     WORD                tec_Top;
  79.     WORD                tec_Width;
  80.     WORD                tec_Height;
  81.  
  82.     LONG                tec_NumLines;
  83.  
  84.     WORD                tec_CharWidth;
  85.     WORD                tec_CharHeight;
  86.  
  87.     LONG                tec_CursorX;
  88.     LONG                tec_CursorY;
  89.  
  90.     struct DrawInfo *    tec_DrawInfo;
  91.     struct TextFont *    tec_Font;
  92.  
  93.     LONG                tec_PreviousFirstLine;
  94.     BOOL                tec_PreviousDataValid;
  95.  
  96.     BOOL                tec_MustCountColumnsAndLines;
  97.  
  98.     struct TextExtent    tec_TextExtent;
  99.     struct RastPort        tec_MeasureRastPort;
  100.     BOOL                tec_MeasureRastPortReady;
  101.  
  102.     APTR                tec_MemoryPoolHeader;
  103. };
  104.  
  105. /******************************************************************************/
  106.  
  107. extern APTR __asm AsmCreatePool(register __d0 ULONG MemFlags,
  108.                                 register __d1 ULONG PuddleSize,
  109.                                 register __d2 ULONG ThreshSize,
  110.                                 register __a6 struct Library * SysBase);
  111.  
  112. extern VOID __asm AsmDeletePool(register __a0 APTR PoolHeader,
  113.                                 register __a6 struct Library * SysBase);
  114.  
  115. extern APTR __asm AsmAllocPooled(register __a0 APTR PoolHeader,
  116.                                  register __d0 ULONG Size,
  117.                                  register __a6 struct Library * SysBase);
  118.  
  119. extern VOID __asm AsmFreePooled(register __a0 APTR PoolHeader,
  120.                                 register __a1 APTR Memory,
  121.                                 register __d0 ULONG MemSize,
  122.                                 register __a6 struct Library * SysBase);
  123.  
  124. /******************************************************************************/
  125.  
  126. STATIC VOID TE_FreeVec(struct TextEditContext * tec,APTR address);
  127. STATIC APTR TE_AllocVec(struct TextEditContext * tec,ULONG size,ULONG attributes);
  128. STATIC VOID TE_SetWriteMask(struct TextEditContext *tec, UBYTE mask);
  129. STATIC VOID TE_SetABPenDrMd(struct TextEditContext *tec, LONG fgPen, LONG bgPen, LONG drawMode);
  130. STATIC ULONG TE_TextLength(struct TextEditContext *tec, STRPTR string, LONG len);
  131. STATIC ULONG TE_TextFit(struct TextEditContext *tec, STRPTR string, LONG len, LONG width);
  132. STATIC ULONG TE_RoundedTextFit(struct TextEditContext *tec, STRPTR string, LONG len, LONG width, LONG *deltaPtr);
  133. STATIC VOID TE_ScrollComplete(struct TextEditContext *tec, LONG deltaX, LONG deltaY);
  134. STATIC LONG TE_StrLen(STRPTR string);
  135. STATIC STRPTR TE_FindLine(struct TextEditContext *tec, LONG whichLine);
  136. STATIC VOID TE_DrawComplete(struct TextEditContext *tec, LONG startLine, LONG stopLine);
  137. STATIC VOID TE_FillArea(struct TextEditContext *tec, LONG left, LONG top, LONG width, LONG height);
  138. STATIC VOID TE_PrintText(struct TextEditContext *tec, LONG skipPixels, LONG left, LONG top, LONG width, STRPTR string, LONG len);
  139. STATIC VOID TE_CursorPositionToOffset(struct TextEditContext *tec, LONG *offsetPtr);
  140. STATIC VOID TE_OffsetToCursorPosition(struct TextEditContext *tec, LONG offset);
  141. STATIC BOOL TE_DetermineLinesAffectedByChanges(struct TextEditContext *tec, LONG firstByteChanged, LONG numBytesChanged, LONG *firstLinePtr, LONG *lastLinePtr);
  142. STATIC VOID TE_MakeBackup(struct TextEditContext *tec);
  143. STATIC VOID TE_CountColumnsAndLines(struct TextEditContext *tec);
  144. STATIC VOID TE_DrawCursor(struct TextEditContext *tec, LONG mode);
  145. STATIC VOID TE_ShowCursor(struct TextEditContext *tec);
  146. STATIC VOID TE_HideCursor(struct TextEditContext *tec);
  147. STATIC VOID TE_EraseCursor(struct TextEditContext *tec);
  148. STATIC BOOL TE_ChooseVisibleOffsetForCursor(struct TextEditContext *tec);
  149. STATIC VOID TE_MakeCursorVisible(struct TextEditContext *tec);
  150. STATIC VOID TE_ValidateCursorX(struct TextEditContext *tec);
  151. STATIC VOID TE_MarkForRedraw(struct TextEditContext *tec, LONG startLine, LONG stopLine);
  152.  
  153. /******************************************************************************/
  154.  
  155. STATIC VOID
  156. TE_FreeVec(
  157.     struct TextEditContext *    tec,
  158.     APTR                        address)
  159. {
  160.     if(address != NULL)
  161.     {
  162.         ULONG * mem = address;
  163.  
  164.         AsmFreePooled(tec->tec_MemoryPoolHeader,&mem[-1],mem[-1],SysBase);
  165.     }
  166. }
  167.  
  168. STATIC APTR
  169. TE_AllocVec(
  170.     struct TextEditContext *    tec,
  171.     ULONG                        size,
  172.     ULONG                        attributes)
  173. {
  174.     APTR result = NULL;
  175.  
  176.     if(size > 0)
  177.     {
  178.         APTR poolHeader;
  179.         ULONG * mem;
  180.  
  181.         if(attributes & MEMF_LOCAL)
  182.             poolHeader = (APTR)tec;
  183.         else
  184.             poolHeader = tec->tec_MemoryPoolHeader;
  185.  
  186.         mem = AsmAllocPooled(poolHeader,sizeof(*mem) + size,SysBase);
  187.         if(mem != NULL)
  188.         {
  189.             (*mem++) = sizeof(*mem) + size;
  190.  
  191.             if(attributes & MEMF_CLEAR)
  192.                 memset(mem,0,size);
  193.  
  194.             result = mem;
  195.         }
  196.     }
  197.  
  198.     return(result);
  199. }
  200.  
  201. /******************************************************************************/
  202.  
  203. #define STARTLINE_First    (-1)
  204. #define STOPLINE_Last    (-1)
  205.  
  206. STATIC VOID
  207. TE_DrawComplete(
  208.     struct TextEditContext *    tec,
  209.     LONG                        startLine,
  210.     LONG                        stopLine)
  211. {
  212.     if(tec->tec_IsDrawable && tec->tec_Height >= tec->tec_CharHeight)
  213.     {
  214.         LONG whichLine,top,lineHeight,numLines,from,to,linesShown,i;
  215.         STRPTR string;
  216.  
  217.         TE_HideCursor(tec);
  218.  
  219.         whichLine = tec->tec_FirstLine;
  220.  
  221.         lineHeight = tec->tec_CharHeight;
  222.         numLines = tec->tec_NumLines;
  223.  
  224.         if(startLine == STARTLINE_First)
  225.             from = 0;
  226.         else
  227.             from = startLine;
  228.  
  229.         whichLine += from;
  230.         top = from * lineHeight;
  231.  
  232.         if(stopLine == STOPLINE_Last)
  233.             to = numLines-1;
  234.         else
  235.             to = stopLine;
  236.  
  237.         TE_SetABPenDrMd(tec,tec->tec_TextPen,tec->tec_BackPen,JAM2);
  238.         TE_SetWriteMask(tec,tec->tec_TextPen | tec->tec_BackPen);
  239.  
  240.         if(NOT tec->tec_BufferChanged && tec->tec_PreviousDataValid)
  241.         {
  242.             LONG numLinesToScroll;
  243.  
  244.             numLinesToScroll = abs(tec->tec_PreviousFirstLine - tec->tec_FirstLine);
  245.  
  246.             if(numLinesToScroll > 0 && numLinesToScroll < tec->tec_NumLines)
  247.             {
  248.                 if(tec->tec_FirstLine < tec->tec_PreviousFirstLine)
  249.                 {
  250.                     TE_ScrollComplete(tec,0,-(numLinesToScroll * lineHeight));
  251.  
  252.                     to = numLinesToScroll-1;
  253.                 }
  254.                 else /* if(tec->tec_FirstLine > tec->tec_PreviousFirstLine) */
  255.                 {
  256.                     TE_ScrollComplete(tec,0,numLinesToScroll * lineHeight);
  257.  
  258.                     from = tec->tec_NumLines-numLinesToScroll;
  259.                     whichLine += from;
  260.                     top += from * lineHeight;
  261.                 }
  262.             }
  263.         }
  264.  
  265.         for(i = from ; i <= to ; i++)
  266.         {
  267.             string = TE_FindLine(tec,whichLine++);
  268.             if(string != NULL)
  269.             {
  270.                 TE_PrintText(tec,tec->tec_FirstPixel,tec->tec_Left,tec->tec_Top + top,tec->tec_Width,string,TE_StrLen(string));
  271.             }
  272.             else
  273.             {
  274.                 SetAPen(tec->tec_RastPort,tec->tec_BackPen);
  275.                 TE_FillArea(tec,tec->tec_Left,tec->tec_Top + top,tec->tec_Width,lineHeight);
  276.                 SetAPen(tec->tec_RastPort,tec->tec_TextPen);
  277.             }
  278.  
  279.             top += lineHeight;
  280.         }
  281.  
  282.         linesShown = tec->tec_MaxLines - tec->tec_FirstLine;
  283.         if(linesShown < numLines)
  284.         {
  285.             SetAPen(tec->tec_RastPort,tec->tec_BackPen);
  286.             TE_FillArea(tec,tec->tec_Left,tec->tec_Top + linesShown * lineHeight,tec->tec_Width,(numLines - linesShown) * lineHeight);
  287.             SetAPen(tec->tec_RastPort,tec->tec_TextPen);
  288.         }
  289.  
  290.         TE_ShowCursor(tec);
  291.     }
  292.  
  293.     tec->tec_MustRedraw        = FALSE;
  294.     tec->tec_BufferChanged    = FALSE;
  295.  
  296.     tec->tec_RedrawStartLine    = tec->tec_NumLines-1;
  297.     tec->tec_RedrawStopLine        = 0;
  298.  
  299.     tec->tec_PreviousFirstLine    = tec->tec_FirstLine;
  300.     tec->tec_PreviousDataValid    = TRUE;
  301. }
  302.  
  303. STATIC VOID
  304. TE_FillArea(
  305.     struct TextEditContext *    tec,
  306.     LONG                        left,
  307.     LONG                        top,
  308.     LONG                        width,
  309.     LONG                        height)
  310. {
  311.     if(width > 0 && height > 0)
  312.     {
  313.         RectFill(tec->tec_RastPort,
  314.             left,top,
  315.             left + width - 1,top + height - 1);
  316.     }
  317. }
  318.  
  319. STATIC VOID
  320. TE_PrintText(
  321.     struct TextEditContext *    tec,
  322.     LONG                        skipPixels,
  323.     LONG                        left,
  324.     LONG                        top,
  325.     LONG                        width,
  326.     STRPTR                        string,
  327.     LONG                        len)
  328. {
  329.     LONG totalChars,delta;
  330.  
  331.     if(skipPixels > 0)
  332.     {
  333.         totalChars = TE_RoundedTextFit(tec,(STRPTR)string,len,skipPixels,&delta);
  334.         if(totalChars > 0)
  335.         {
  336.             string += totalChars;
  337.             len -= totalChars;
  338.         }
  339.     }
  340.     else
  341.     {
  342.         delta = 0;
  343.     }
  344.  
  345.     if(len > 0)
  346.     {
  347.         totalChars = TE_TextFit(tec,(STRPTR)string,len,width - delta);
  348.         if(totalChars > 0)
  349.         {
  350.             Move(tec->tec_RastPort,left + delta - tec->tec_TextExtent.te_Extent.MinX,top+tec->tec_RastPort->TxBaseline);
  351.             Text(tec->tec_RastPort,(STRPTR)string,totalChars);
  352.         }
  353.  
  354.         if(delta > 0)
  355.         {
  356.             SetAPen(tec->tec_RastPort,tec->tec_BackPen);
  357.             TE_FillArea(tec,left,top,delta,tec->tec_CharHeight);
  358.             SetAPen(tec->tec_RastPort,tec->tec_TextPen);
  359.  
  360.             left += delta;
  361.             width -= delta;
  362.         }
  363.     }
  364.     else
  365.     {
  366.         tec->tec_TextExtent.te_Width = 0;
  367.     }
  368.  
  369.     if(width > tec->tec_TextExtent.te_Width)
  370.     {
  371.         SetAPen(tec->tec_RastPort,tec->tec_BackPen);
  372.         TE_FillArea(tec,left + tec->tec_TextExtent.te_Width,top,width - tec->tec_TextExtent.te_Width,tec->tec_CharHeight);
  373.         SetAPen(tec->tec_RastPort,tec->tec_TextPen);
  374.     }
  375. }
  376.  
  377. /******************************************************************************/
  378.  
  379. STATIC VOID
  380. TE_SetWriteMask(
  381.     struct TextEditContext *    tec,
  382.     UBYTE                        mask)
  383. {
  384.     if(GfxBase->lib_Version < 39)
  385.         tec->tec_RastPort->Mask = mask;
  386.     else
  387.         SetWriteMask(tec->tec_RastPort,mask);
  388. }
  389.  
  390. /******************************************************************************/
  391.  
  392. #define OLD_FgPen        (-1)
  393. #define OLD_BgPen        (-1)
  394. #define OLD_DrawMode    (-1)
  395.  
  396. STATIC VOID
  397. TE_SetABPenDrMd(
  398.     struct TextEditContext *    tec,
  399.     LONG                        fgPen,
  400.     LONG                        bgPen,
  401.     LONG                        drawMode)
  402. {
  403.     if(GfxBase->lib_Version < 39)
  404.     {
  405.         if(fgPen != OLD_FgPen)
  406.             SetAPen(tec->tec_RastPort,fgPen);
  407.  
  408.         if(bgPen != OLD_BgPen)
  409.             SetBPen(tec->tec_RastPort,bgPen);
  410.  
  411.         if(drawMode != OLD_DrawMode)
  412.             SetDrMd(tec->tec_RastPort,drawMode);
  413.     }
  414.     else
  415.     {
  416.         if(fgPen == OLD_FgPen)
  417.             fgPen = GetAPen(tec->tec_RastPort);
  418.  
  419.         if(bgPen == OLD_BgPen)
  420.             bgPen = GetBPen(tec->tec_RastPort);
  421.  
  422.         if(drawMode == OLD_DrawMode)
  423.             drawMode = GetDrMd(tec->tec_RastPort);
  424.  
  425.         SetABPenDrMd(tec->tec_RastPort,fgPen,bgPen,drawMode);
  426.     }
  427. }
  428.  
  429. /******************************************************************************/
  430.  
  431. STATIC ULONG
  432. TE_TextLength(
  433.     struct TextEditContext *    tec,
  434.     STRPTR                        string,
  435.     LONG                        len)
  436. {
  437.     ULONG result;
  438.  
  439.     TextFit(&tec->tec_MeasureRastPort,string,len,&tec->tec_TextExtent,NULL,1,32767,32767);
  440.  
  441.     result = tec->tec_TextExtent.te_Width + (-tec->tec_TextExtent.te_Extent.MinX);
  442.  
  443.     return(result);
  444. }
  445.  
  446. STATIC ULONG
  447. TE_TextFit(
  448.     struct TextEditContext *    tec,
  449.     STRPTR                        string,
  450.     LONG                        len,
  451.     LONG                        width)
  452. {
  453.     ULONG result;
  454.  
  455.     result = TextFit(&tec->tec_MeasureRastPort,string,len,&tec->tec_TextExtent,NULL,1,width,32767);
  456.  
  457.     return(result);
  458. }
  459.  
  460. STATIC ULONG
  461. TE_RoundedTextFit(
  462.     struct TextEditContext *    tec,
  463.     STRPTR                        string,
  464.     LONG                        len,
  465.     LONG                        width,
  466.     LONG *                        deltaPtr)
  467. {
  468.     ULONG chars;
  469.     LONG delta = 0;
  470.  
  471.     chars = TE_TextFit(tec,string,len,width);
  472.     if(chars < len)
  473.     {
  474.         if(chars == 0 || TE_TextLength(tec,string,chars) != width)
  475.         {
  476.             chars++;
  477.  
  478.             delta = TE_TextLength(tec,string,chars) - width;
  479.         }
  480.     }
  481.  
  482.     (*deltaPtr) = delta;
  483.  
  484.     return(chars);
  485. }
  486.  
  487. /******************************************************************************/
  488.  
  489. STATIC VOID
  490. TE_ScrollComplete(
  491.     struct TextEditContext *    tec,
  492.     LONG                        deltaX,
  493.     LONG                        deltaY)
  494. {
  495.     if(GfxBase->lib_Version < 39)
  496.     {
  497.         ScrollRaster(tec->tec_RastPort,deltaX,deltaY,
  498.             tec->tec_Left,tec->tec_Top,
  499.             tec->tec_Left + tec->tec_Width-1,tec->tec_Top + tec->tec_NumLines*tec->tec_CharHeight - 1);
  500.     }
  501.     else
  502.     {
  503.         struct Hook * oldHook;
  504.  
  505.         LockLayerInfo(tec->tec_RastPort->Layer->LayerInfo);
  506.         oldHook = InstallLayerHook(tec->tec_RastPort->Layer,LAYERS_NOBACKFILL);
  507.  
  508.         ScrollRasterBF(tec->tec_RastPort,deltaX,deltaY,
  509.             tec->tec_Left,tec->tec_Top,
  510.             tec->tec_Left + tec->tec_Width-1,tec->tec_Top + tec->tec_NumLines*tec->tec_CharHeight - 1);
  511.  
  512.         InstallLayerHook(tec->tec_RastPort->Layer,oldHook);
  513.         UnlockLayerInfo(tec->tec_RastPort->Layer->LayerInfo);
  514.     }
  515. }
  516.  
  517. /******************************************************************************/
  518.  
  519. VOID
  520. TE_GetTextEditString(
  521.     struct TextEditContext *    tec,
  522.     STRPTR *                    stringPtr)
  523. {
  524.     (*stringPtr) = tec->tec_String;
  525. }
  526.  
  527. BOOL
  528. TE_SetTextEditString(
  529.     struct TextEditContext *    tec,
  530.     STRPTR                        string)
  531. {
  532.     BOOL hasNewBuffer = FALSE;
  533.     STRPTR newString;
  534.     LONG len;
  535.  
  536.     if(string == NULL)
  537.         string = "";
  538.  
  539.     len = strlen(string)+1;
  540.  
  541.     newString = TE_AllocVec(tec,len + GRANULARITY,MEMF_ANY|MEMF_PUBLIC);
  542.     if(newString != NULL)
  543.     {
  544.         hasNewBuffer = TRUE;
  545.  
  546.         strcpy(newString,string);
  547.  
  548.         if(tec->tec_String != NULL)
  549.             TE_FreeVec(tec,tec->tec_String);
  550.  
  551.         tec->tec_String                = newString;
  552.         tec->tec_StringUsedSize        = len;
  553.         tec->tec_StringTotalSize    = len + GRANULARITY;
  554.  
  555.         tec->tec_LinePointer        = tec->tec_String;
  556.         tec->tec_LineIndex            = 0;
  557.  
  558.         if(tec->tec_MeasureRastPortReady)
  559.             TE_CountColumnsAndLines(tec);
  560.         else
  561.             tec->tec_MustCountColumnsAndLines = TRUE;
  562.  
  563.         TE_MakeBackup(tec);
  564.     }
  565.  
  566.     return(hasNewBuffer);
  567. }
  568.  
  569. /******************************************************************************/
  570.  
  571. VOID
  572. TE_GetTextEditStringPosition(
  573.     struct TextEditContext *    tec,
  574.     LONG *                        positionPtr)
  575. {
  576.     TE_CursorPositionToOffset(tec,positionPtr);
  577. }
  578.  
  579. VOID
  580. TE_SetTextEditStringPosition(
  581.     struct TextEditContext *    tec,
  582.     LONG                        position)
  583. {
  584.     if(position < 0 || position > tec->tec_StringUsedSize)
  585.         position = tec->tec_StringUsedSize;
  586.  
  587.     TE_HideCursor(tec);
  588.  
  589.     TE_OffsetToCursorPosition(tec,position);
  590.     TE_ChooseVisibleOffsetForCursor(tec);
  591.  
  592.     TE_MarkForRedraw(tec,STARTLINE_First,STOPLINE_Last);
  593.  
  594.     TE_ShowCursor(tec);
  595. }
  596.  
  597. /******************************************************************************/
  598.  
  599. VOID
  600. TE_DeleteTextEditContext(struct TextEditContext * tec)
  601. {
  602.     if(tec != NULL)
  603.         AsmDeletePool(tec->tec_MemoryPoolHeader,SysBase);
  604. }
  605.  
  606. struct TextEditContext *
  607. TE_CreateTextEditContext(
  608.     struct DrawInfo *    dri,
  609.     struct TextFont *    font)
  610. {
  611.     struct TextEditContext * tec = NULL;
  612.     APTR memoryPoolHeader;
  613.  
  614.     memoryPoolHeader = AsmCreatePool(MEMF_ANY|MEMF_PUBLIC,2048,2048,SysBase);
  615.     if(memoryPoolHeader != NULL)
  616.     {
  617.         tec = TE_AllocVec((struct TextEditContext *)memoryPoolHeader,sizeof(*tec),MEMF_ANY|MEMF_CLEAR|MEMF_LOCAL);
  618.         if(tec != NULL)
  619.         {
  620.             tec->tec_DrawInfo = dri;
  621.  
  622.             tec->tec_ShadowPen            = dri->dri_Pens[SHADOWPEN];
  623.             tec->tec_ActiveTextPen        = dri->dri_Pens[TEXTPEN];
  624.             tec->tec_ActiveBackPen        = dri->dri_Pens[BACKGROUNDPEN];
  625.             tec->tec_InactiveTextPen    = dri->dri_Pens[TEXTPEN];
  626.             tec->tec_InactiveBackPen    = dri->dri_Pens[BACKGROUNDPEN];
  627.  
  628.             tec->tec_TextPen = tec->tec_InactiveTextPen;
  629.             tec->tec_BackPen = tec->tec_InactiveBackPen;
  630.  
  631.             if(font == NULL)
  632.                 font = dri->dri_Font;
  633.  
  634.             tec->tec_Font = font;
  635.  
  636.             tec->tec_CharWidth    = tec->tec_Font->tf_XSize;
  637.             tec->tec_CharHeight    = tec->tec_Font->tf_YSize;
  638.  
  639.             tec->tec_CursorVisible = VISIBLE+1;
  640.  
  641.             tec->tec_MemoryPoolHeader = memoryPoolHeader;
  642.         }
  643.         else
  644.         {
  645.             AsmDeletePool(memoryPoolHeader,SysBase);
  646.         }
  647.     }
  648.  
  649.     return(tec);
  650. }
  651.  
  652. /******************************************************************************/
  653.  
  654. VOID
  655. TE_SetTextEditBox(
  656.     struct TextEditContext *    tec,
  657.     struct IBox *                box)
  658. {
  659.     if(tec->tec_DrawInfo != NULL)
  660.     {
  661.         tec->tec_Left        = box->Left;
  662.         tec->tec_Top        = box->Top;
  663.         tec->tec_Width        = box->Width;
  664.         tec->tec_Height        = box->Height;
  665.         tec->tec_NumLines    = box->Height / tec->tec_CharHeight;
  666.  
  667.         tec->tec_RedrawStartLine    = tec->tec_NumLines-1;
  668.         tec->tec_RedrawStopLine        = 0;
  669.     }
  670. }
  671.  
  672. VOID
  673. TE_SetTextEditRastPort(
  674.     struct TextEditContext *    tec,
  675.     struct RastPort *            rastPort)
  676. {
  677.     if(rastPort != NULL)
  678.     {
  679.         tec->tec_RastPort = rastPort;
  680.         SetFont(tec->tec_RastPort,tec->tec_Font);
  681.  
  682.         if(NOT tec->tec_MeasureRastPortReady)
  683.         {
  684.             tec->tec_MeasureRastPort        = (*rastPort);
  685.             tec->tec_MeasureRastPortReady    = TRUE;
  686.         }
  687.  
  688.         if(tec->tec_MustCountColumnsAndLines)
  689.             TE_CountColumnsAndLines(tec);
  690.  
  691.         tec->tec_IsDrawable = TRUE;
  692.     }
  693.     else
  694.     {
  695.         tec->tec_IsDrawable = FALSE;
  696.     }
  697. }
  698.  
  699. /******************************************************************************/
  700.  
  701. STATIC LONG
  702. TE_StrLen(STRPTR string)
  703. {
  704.     LONG len = 0;
  705.  
  706.     if(string != NULL)
  707.     {
  708.         while((*string) != '\n' && (*string) != '\0')
  709.         {
  710.             string++;
  711.  
  712.             len++;
  713.         }
  714.     }
  715.  
  716.     return(len);
  717. }
  718.  
  719. STATIC STRPTR
  720. TE_FindLine(
  721.     struct TextEditContext *    tec,
  722.     LONG                        whichLine)
  723. {
  724.     STRPTR result = NULL;
  725.  
  726.     if(tec->tec_LineIndex == whichLine)
  727.     {
  728.         result = tec->tec_LinePointer;
  729.     }
  730.     else
  731.     {
  732.         if(whichLine < tec->tec_LineIndex)
  733.         {
  734.             if(whichLine >= 0)
  735.             {
  736.                 STRPTR lastLineFeed;
  737.                 STRPTR lastChar;
  738.                 LONG line;
  739.                 STRPTR s;
  740.  
  741.                 line    = tec->tec_LineIndex;
  742.                 s        = tec->tec_LinePointer;
  743.  
  744.                 lastLineFeed    = tec->tec_LinePointer-1;
  745.                 lastChar        = tec->tec_String-1;
  746.  
  747.                 while((line > whichLine) && (s != lastChar))
  748.                 {
  749.                     s--;
  750.  
  751.                     if(((*s) == '\n' && s != lastLineFeed) || (s == lastChar))
  752.                         line--; /* found another line */
  753.                 }
  754.  
  755.                 if(line == whichLine)
  756.                 {
  757.                     tec->tec_LineIndex        = line;
  758.                     tec->tec_LinePointer    = s+1;
  759.  
  760.                     result = tec->tec_LinePointer;
  761.                 }
  762.             }
  763.         }
  764.         else /* if(whichLine > tec->tec_LineIndex) */
  765.         {
  766.             LONG line;
  767.             STRPTR s;
  768.  
  769.             line    = tec->tec_LineIndex;
  770.             s        = tec->tec_LinePointer;
  771.  
  772.             while((line < whichLine) && ((*s) != '\0'))
  773.             {
  774.                 if((*s++) == '\n')
  775.                     line++;        /* found another line */
  776.             }
  777.  
  778.             if(line == whichLine)
  779.             {
  780.                 tec->tec_LineIndex        = line;
  781.                 tec->tec_LinePointer    = s;
  782.  
  783.                 result = tec->tec_LinePointer;
  784.             }
  785.         }
  786.     }
  787.  
  788.     return(result);
  789. }
  790.  
  791. /******************************************************************************/
  792.  
  793. STATIC VOID
  794. TE_CursorPositionToOffset(
  795.     struct TextEditContext *    tec,
  796.     LONG *                        offsetPtr)
  797. {
  798.     STRPTR string;
  799.  
  800.     string = TE_FindLine(tec,tec->tec_CursorY);
  801.     if(string != NULL)
  802.         (*offsetPtr) = ((LONG)string - (LONG)tec->tec_String) + tec->tec_CursorX;
  803. }
  804.  
  805. STATIC VOID
  806. TE_OffsetToCursorPosition(
  807.     struct TextEditContext *    tec,
  808.     LONG                        offset)
  809. {
  810.     if(offset >= 0)
  811.     {
  812.         STRPTR stringOffset;
  813.         STRPTR string;
  814.         LONG whichLine;
  815.  
  816.         stringOffset = tec->tec_String + offset;
  817.  
  818.         for(whichLine = 0 ; (string = TE_FindLine(tec,whichLine)) != NULL ; whichLine++)
  819.         {
  820.             if(string <= stringOffset && stringOffset <= string + TE_StrLen(string))
  821.             {
  822.                 TE_HideCursor(tec);
  823.  
  824.                 tec->tec_CursorX = (LONG)stringOffset - (LONG)string;
  825.                 tec->tec_CursorY = whichLine;
  826.  
  827.                 TE_ShowCursor(tec);
  828.  
  829.                 break;
  830.             }
  831.         }
  832.     }
  833. }
  834.  
  835. /******************************************************************************/
  836.  
  837. STATIC BOOL
  838. TE_DetermineLinesAffectedByChanges(
  839.     struct TextEditContext *    tec,
  840.     LONG                        firstByteChanged,
  841.     LONG                        numBytesChanged,
  842.     LONG *                        firstLinePtr,
  843.     LONG *                        lastLinePtr)
  844. {
  845.     STRPTR firstCharDisplayed;
  846.     STRPTR lastCharDisplayed;
  847.     LONG lastLineDisplayed;
  848.     BOOL changesAreVisible;
  849.  
  850.     changesAreVisible = FALSE;
  851.  
  852.     lastLineDisplayed = tec->tec_FirstLine + tec->tec_NumLines-1;
  853.     if(lastLineDisplayed >= tec->tec_MaxLines)
  854.     {
  855.         lastLineDisplayed = tec->tec_MaxLines-1;
  856.         if(lastLineDisplayed < 0)
  857.             lastLineDisplayed = 0;
  858.     }
  859.  
  860.     firstCharDisplayed    = TE_FindLine(tec,tec->tec_FirstLine);
  861.     lastCharDisplayed    = TE_FindLine(tec,lastLineDisplayed);
  862.  
  863.     if(firstCharDisplayed != NULL && lastCharDisplayed != NULL)
  864.     {
  865.         STRPTR firstCharChanged;
  866.         STRPTR lastCharChanged;
  867.  
  868.         lastCharDisplayed += TE_StrLen(lastCharDisplayed)-1;
  869.  
  870.         firstCharChanged    = tec->tec_String + firstByteChanged;
  871.         lastCharChanged        = tec->tec_String + firstByteChanged + numBytesChanged - 1;
  872.  
  873.         if(firstCharDisplayed <= lastCharChanged && firstCharChanged <= lastCharDisplayed)
  874.         {
  875.             STRPTR string;
  876.             LONG firstLine;
  877.             LONG lastLine;
  878.             LONG len;
  879.             LONG i;
  880.  
  881.             if(firstCharChanged < firstCharDisplayed)
  882.                 firstCharChanged = firstCharDisplayed;
  883.  
  884.             if(lastCharChanged > lastCharDisplayed)
  885.                 lastCharChanged = lastCharDisplayed;
  886.  
  887.             firstLine = lastLine = -1;
  888.  
  889.             for(i = 0 ; i < tec->tec_NumLines ; i++)
  890.             {
  891.                 string = TE_FindLine(tec,tec->tec_FirstLine + i);
  892.                 if(string != NULL)
  893.                 {
  894.                     len = TE_StrLen(string);
  895.  
  896.                     if(string <= firstCharChanged && firstCharChanged <= string + len)
  897.                     {
  898.                         if(firstLine == -1)
  899.                             firstLine = i;
  900.                     }
  901.  
  902.                     if(string <= lastCharChanged && lastCharChanged <= string + len)
  903.                     {
  904.                         lastLine = i;
  905.  
  906.                         changesAreVisible = TRUE;
  907.                     }
  908.                     else if (lastLine != -1)
  909.                     {
  910.                         break;
  911.                     }
  912.                 }
  913.             }
  914.  
  915.             if(changesAreVisible)
  916.             {
  917.                 (*firstLinePtr)    = firstLine;
  918.                 (*lastLinePtr)    = lastLine;
  919.             }
  920.         }
  921.     }
  922.  
  923.     return(changesAreVisible);
  924. }
  925.  
  926. /******************************************************************************/
  927.  
  928. BOOL
  929. TE_AddString(
  930.     struct TextEditContext *    tec,
  931.     UBYTE *                        string,
  932.     LONG                        len)
  933. {
  934.     LONG bytesBefore,bytesAfter;
  935.     STRPTR destBuffer;
  936.     LONG offset;
  937.     LONG firstLine,lastLine;
  938.     BOOL successful = FALSE;
  939.  
  940.     TE_CursorPositionToOffset(tec,&offset);
  941.  
  942.     bytesBefore    = offset;
  943.     bytesAfter    = tec->tec_StringUsedSize - bytesBefore;
  944.  
  945.     TE_HideCursor(tec);
  946.  
  947.     if(tec->tec_StringUsedSize + len < tec->tec_StringTotalSize)
  948.     {
  949.         destBuffer = tec->tec_String;
  950.  
  951.         if(bytesAfter > 0)
  952.             memmove(destBuffer + offset + len,destBuffer + offset,bytesAfter);
  953.     }
  954.     else
  955.     {
  956.         LONG destBufferSize;
  957.  
  958.         destBufferSize = tec->tec_StringUsedSize + len + GRANULARITY;
  959.  
  960.         destBuffer = TE_AllocVec(tec,destBufferSize,MEMF_ANY|MEMF_PUBLIC);
  961.         if(destBuffer != NULL)
  962.         {
  963.             if(bytesBefore > 0)
  964.                 memcpy(destBuffer,tec->tec_String,bytesBefore);
  965.  
  966.             if(bytesAfter > 0)
  967.                 memcpy(destBuffer + offset + len,tec->tec_String + bytesBefore,bytesAfter);
  968.  
  969.             if(tec->tec_String != NULL)
  970.                 TE_FreeVec(tec,tec->tec_String);
  971.  
  972.             tec->tec_String                = destBuffer;
  973.             tec->tec_StringTotalSize    = destBufferSize;
  974.         }
  975.     }
  976.  
  977.     if(destBuffer != NULL)
  978.     {
  979.         LONG numBytesChanged,i;
  980.  
  981.         memcpy(destBuffer + offset,string,len);
  982.         tec->tec_StringUsedSize += len;
  983.  
  984.         tec->tec_BufferChanged = TRUE;
  985.  
  986.         tec->tec_LinePointer    = tec->tec_String;
  987.         tec->tec_LineIndex        = 0;
  988.  
  989.         TE_CountColumnsAndLines(tec);
  990.         TE_OffsetToCursorPosition(tec,offset + len);
  991.         TE_ChooseVisibleOffsetForCursor(tec);
  992.  
  993.         numBytesChanged = len;
  994.  
  995.         for(i = 0 ; i < len ; i++)
  996.         {
  997.             if(string[i] == '\n')
  998.             {
  999.                 numBytesChanged = tec->tec_StringUsedSize - offset;
  1000.                 break;
  1001.             }
  1002.         }
  1003.  
  1004.         firstLine    = STARTLINE_First;
  1005.         lastLine    = STOPLINE_Last;
  1006.  
  1007.         TE_DetermineLinesAffectedByChanges(tec,
  1008.             offset,numBytesChanged,
  1009.             &firstLine,&lastLine);
  1010.  
  1011.         TE_MarkForRedraw(tec,firstLine,lastLine);
  1012.  
  1013.         successful = TRUE;
  1014.     }
  1015.  
  1016.     TE_ShowCursor(tec);
  1017.  
  1018.     return(successful);
  1019. }
  1020.  
  1021. VOID
  1022. TE_RemoveChars(
  1023.     struct TextEditContext *    tec,
  1024.     LONG                        numChars)
  1025. {
  1026.     if(numChars > 0)
  1027.     {
  1028.         LONG offset;
  1029.  
  1030.         TE_CursorPositionToOffset(tec,&offset);
  1031.  
  1032.         if(numChars > offset)
  1033.             numChars = offset;
  1034.  
  1035.         if(numChars > 0)
  1036.         {
  1037.             LONG firstLine,lastLine,numBytesChanged,i;
  1038.             BOOL anyLinesRemoved;
  1039.  
  1040.             anyLinesRemoved = FALSE;
  1041.             for(i = 0 ; i < numChars ; i++)
  1042.             {
  1043.                 if(tec->tec_String[offset - numChars + i] == '\n')
  1044.                 {
  1045.                     anyLinesRemoved = TRUE;
  1046.                     break;
  1047.                 }
  1048.             }
  1049.  
  1050.             TE_HideCursor(tec);
  1051.  
  1052.             firstLine    = STARTLINE_First;
  1053.             lastLine    = STOPLINE_Last;
  1054.  
  1055.             if(anyLinesRemoved)
  1056.             {
  1057.                 /* This doesn't work since the display may have moved
  1058.                  * horizontally after deleting the first characters of
  1059.                  * a line.
  1060.                  */
  1061.                 /*numBytesChanged = tec->tec_StringUsedSize - offset;
  1062.  
  1063.                 TE_DetermineLinesAffectedByChanges(tec,
  1064.                     offset,numBytesChanged,
  1065.                     &firstLine,&lastLine);*/
  1066.             }
  1067.             else
  1068.             {
  1069.                 numBytesChanged = TE_StrLen(tec->tec_String + offset - numChars);
  1070.  
  1071.                 /* Account for the terminating '\0'. */
  1072.                 if(numBytesChanged == 0)
  1073.                     numBytesChanged = 1;
  1074.  
  1075.                 TE_DetermineLinesAffectedByChanges(tec,
  1076.                     offset,numBytesChanged,
  1077.                     &firstLine,&lastLine);
  1078.             }
  1079.  
  1080.             memmove(tec->tec_String + offset - numChars,tec->tec_String + offset,tec->tec_StringUsedSize - offset);
  1081.  
  1082.             tec->tec_BufferChanged = TRUE;
  1083.  
  1084.             tec->tec_LinePointer    = tec->tec_String;
  1085.             tec->tec_LineIndex        = 0;
  1086.  
  1087.             tec->tec_StringUsedSize -= numChars;
  1088.  
  1089.             TE_CountColumnsAndLines(tec);
  1090.             TE_OffsetToCursorPosition(tec,offset - numChars);
  1091.             TE_ChooseVisibleOffsetForCursor(tec);
  1092.  
  1093.             TE_MarkForRedraw(tec,firstLine,lastLine);
  1094.  
  1095.             TE_ShowCursor(tec);
  1096.         }
  1097.     }
  1098. }
  1099.  
  1100. VOID
  1101. TE_DeleteChars(
  1102.     struct TextEditContext *    tec,
  1103.     LONG                        numChars)
  1104. {
  1105.     if(numChars > 0)
  1106.     {
  1107.         LONG offset;
  1108.  
  1109.         TE_CursorPositionToOffset(tec,&offset);
  1110.  
  1111.         if(offset + numChars > tec->tec_StringUsedSize)
  1112.             numChars = tec->tec_StringUsedSize - offset;
  1113.  
  1114.         if(numChars > 0)
  1115.         {
  1116.             LONG firstLine,lastLine,numBytesChanged,i;
  1117.             BOOL anyLinesRemoved;
  1118.  
  1119.             anyLinesRemoved = FALSE;
  1120.             for(i = 0 ; i < numChars ; i++)
  1121.             {
  1122.                 if(tec->tec_String[offset + i] == '\n')
  1123.                 {
  1124.                     anyLinesRemoved = TRUE;
  1125.                     break;
  1126.                 }
  1127.             }
  1128.  
  1129.             TE_HideCursor(tec);
  1130.  
  1131.             if(anyLinesRemoved)
  1132.             {
  1133.                 numBytesChanged = tec->tec_StringUsedSize - offset;
  1134.             }
  1135.             else
  1136.             {
  1137.                 numBytesChanged = TE_StrLen(tec->tec_String + offset);
  1138.  
  1139.                 /* Account for the terminating '\0'. */
  1140.                 if(numBytesChanged == 0)
  1141.                     numBytesChanged = 1;
  1142.             }
  1143.  
  1144.             firstLine    = STARTLINE_First;
  1145.             lastLine    = STOPLINE_Last;
  1146.  
  1147.             TE_DetermineLinesAffectedByChanges(tec,
  1148.                 offset,numBytesChanged,
  1149.                 &firstLine,&lastLine);
  1150.  
  1151.             memmove(tec->tec_String + offset,tec->tec_String + offset + numChars,tec->tec_StringUsedSize - offset - numChars);
  1152.  
  1153.             tec->tec_BufferChanged = TRUE;
  1154.  
  1155.             tec->tec_LinePointer    = tec->tec_String;
  1156.             tec->tec_LineIndex        = 0;
  1157.  
  1158.             tec->tec_StringUsedSize -= numChars;
  1159.  
  1160.             TE_CountColumnsAndLines(tec);
  1161.  
  1162.             TE_MarkForRedraw(tec,firstLine,lastLine);
  1163.  
  1164.             TE_ShowCursor(tec);
  1165.         }
  1166.     }
  1167. }
  1168.  
  1169. VOID
  1170. TE_DeleteToStartOfLine(struct TextEditContext * tec)
  1171. {
  1172.     if(tec->tec_CursorX > 0)
  1173.         TE_RemoveChars(tec,tec->tec_CursorX);
  1174. }
  1175.  
  1176. VOID
  1177. TE_DeleteToEndOfLine(struct TextEditContext * tec)
  1178. {
  1179.     STRPTR string;
  1180.  
  1181.     string = TE_FindLine(tec,tec->tec_CursorY);
  1182.     if(string != NULL)
  1183.     {
  1184.         LONG charsFollowingCursor;
  1185.  
  1186.         charsFollowingCursor = TE_StrLen(string) - tec->tec_CursorX;
  1187.         if(charsFollowingCursor > 0)
  1188.             TE_DeleteChars(tec,charsFollowingCursor);
  1189.     }
  1190. }
  1191.  
  1192. VOID
  1193. TE_DeleteAll(struct TextEditContext * tec)
  1194. {
  1195.     if(tec->tec_StringUsedSize > 1) /* one byte reserved for terminator '\0' */
  1196.     {
  1197.         TE_HideCursor(tec);
  1198.  
  1199.         TE_CursorFirstLine(tec);
  1200.         TE_CursorStartOfLine(tec);
  1201.  
  1202.         TE_DeleteChars(tec,tec->tec_StringUsedSize-1);
  1203.         TE_ChooseVisibleOffsetForCursor(tec);
  1204.  
  1205.         TE_ShowCursor(tec);
  1206.     }
  1207. }
  1208.  
  1209. VOID
  1210. TE_RemoveWord(struct TextEditContext * tec)
  1211. {
  1212.     STRPTR string;
  1213.  
  1214.     string = TE_FindLine(tec,tec->tec_CursorY);
  1215.     if(string != NULL)
  1216.     {
  1217.         LONG firstChar,lastChar;
  1218.         LONG i;
  1219.  
  1220.         firstChar = -1;
  1221.         lastChar = -1;
  1222.  
  1223.         for(i = tec->tec_CursorX-1 ; i >= 0 ; i--)
  1224.         {
  1225.             if(i == 0 && lastChar != -1)
  1226.             {
  1227.                 firstChar = 0;
  1228.                 break;
  1229.             }
  1230.             else
  1231.             {
  1232.                 if(string[i] != ' ')
  1233.                 {
  1234.                     if(lastChar == -1)
  1235.                         lastChar = i;
  1236.                 }
  1237.                 else
  1238.                 {
  1239.                     if(lastChar != -1)
  1240.                     {
  1241.                         firstChar = i+1;
  1242.                         break;
  1243.                     }
  1244.                 }
  1245.             }
  1246.         }
  1247.  
  1248.         if(firstChar != -1 && lastChar != -1)
  1249.         {
  1250.             TE_HideCursor(tec);
  1251.  
  1252.             if(firstChar < tec->tec_CursorX)
  1253.                 TE_CursorLeft(tec,tec->tec_CursorX - firstChar);
  1254.  
  1255.             TE_DeleteChars(tec,lastChar - firstChar + 1);
  1256.  
  1257.             TE_ShowCursor(tec);
  1258.         }
  1259.     }
  1260. }
  1261.  
  1262. /******************************************************************************/
  1263.  
  1264. VOID
  1265. TE_RestoreBackup(struct TextEditContext * tec)
  1266. {
  1267.     if(tec->tec_BackupString != NULL)
  1268.     {
  1269.         LONG x,y,firstLine;
  1270.  
  1271.         firstLine    = tec->tec_FirstLine;
  1272.         x            = tec->tec_CursorX;
  1273.         y            = tec->tec_CursorY;
  1274.  
  1275.         TE_DeleteAll(tec);
  1276.         TE_AddString(tec,tec->tec_BackupString,strlen(tec->tec_BackupString));
  1277.  
  1278.         if(y > tec->tec_MaxLines)
  1279.             y = tec->tec_MaxLines;
  1280.  
  1281.         if(firstLine > tec->tec_MaxLines - tec->tec_NumLines)
  1282.         {
  1283.             firstLine = tec->tec_MaxLines - tec->tec_NumLines;
  1284.             if(firstLine < 0)
  1285.                 firstLine = 0;
  1286.         }
  1287.  
  1288.         TE_HideCursor(tec);
  1289.  
  1290.         tec->tec_FirstLine    = firstLine;
  1291.         tec->tec_CursorX    = x;
  1292.         tec->tec_CursorY    = y;
  1293.  
  1294.         TE_ValidateCursorX(tec);
  1295.         TE_ChooseVisibleOffsetForCursor(tec);
  1296.         TE_MarkForRedraw(tec,STARTLINE_First,STOPLINE_Last);
  1297.  
  1298.         TE_ShowCursor(tec);
  1299.     }
  1300.     else
  1301.     {
  1302.         if(tec->tec_IsDrawable)
  1303.             DisplayBeep(NULL);
  1304.     }
  1305. }
  1306.  
  1307. STATIC VOID
  1308. TE_MakeBackup(struct TextEditContext * tec)
  1309. {
  1310.     LONG len;
  1311.  
  1312.     len = strlen(tec->tec_String)+1;
  1313.  
  1314.     if(tec->tec_BackupString != NULL && tec->tec_BackupStringSize >= len)
  1315.     {
  1316.         strcpy(tec->tec_BackupString,tec->tec_String);
  1317.     }
  1318.     else
  1319.     {
  1320.         STRPTR string;
  1321.  
  1322.         if(tec->tec_BackupString != NULL)
  1323.         {
  1324.             TE_FreeVec(tec,tec->tec_BackupString);
  1325.             tec->tec_BackupString = NULL;
  1326.         }
  1327.  
  1328.         string = TE_AllocVec(tec,len,MEMF_ANY|MEMF_PUBLIC);
  1329.         if(string != NULL)
  1330.         {
  1331.             tec->tec_BackupString        = string;
  1332.             tec->tec_BackupStringSize    = len;
  1333.  
  1334.             strcpy(tec->tec_BackupString,tec->tec_String);
  1335.         }
  1336.     }
  1337. }
  1338.  
  1339. /******************************************************************************/
  1340.  
  1341. STATIC VOID
  1342. TE_CountColumnsAndLines(struct TextEditContext * tec)
  1343. {
  1344.     STRPTR string;
  1345.     LONG whichLine = 0;
  1346.     LONG numLines = 0;
  1347.     LONG width,maxWidth = 0;
  1348.     LONG len,maxLen = 0;
  1349.  
  1350.     while((string = TE_FindLine(tec,whichLine++)) != NULL)
  1351.     {
  1352.         numLines++;
  1353.  
  1354.         len = TE_StrLen(string);
  1355.         if(maxLen < len)
  1356.             maxLen = len;
  1357.  
  1358.         width = TE_TextLength(tec,string,len);
  1359.         if(maxWidth < width)
  1360.             maxWidth = width;
  1361.     }
  1362.  
  1363.     tec->tec_MaxPixels                    = maxWidth;
  1364.     tec->tec_MaxColumns                    = maxLen;
  1365.     tec->tec_MaxLines                    = numLines;
  1366.     tec->tec_MustCountColumnsAndLines    = TRUE;
  1367. }
  1368.  
  1369. /******************************************************************************/
  1370.  
  1371. enum
  1372. {
  1373.     DRAWCURSOR_Toggle,
  1374.     DRAWCURSOR_Erase
  1375. };
  1376.  
  1377. STATIC VOID
  1378. TE_DrawCursor(
  1379.     struct TextEditContext *    tec,
  1380.     LONG                        mode)
  1381. {
  1382.     if(tec->tec_IsDrawable)
  1383.     {
  1384.         if(tec->tec_CursorY >= tec->tec_FirstLine &&
  1385.            tec->tec_CursorY  < tec->tec_FirstLine + tec->tec_NumLines)
  1386.         {
  1387.             STRPTR string;
  1388.  
  1389.             string = TE_FindLine(tec,tec->tec_CursorY);
  1390.             if(string != NULL)
  1391.             {
  1392.                 LONG cursorX;
  1393.                 LONG totalChars;
  1394.                 LONG len;
  1395.                 LONG delta;
  1396.  
  1397.                 cursorX = tec->tec_CursorX;
  1398.                 len = TE_StrLen(string);
  1399.                 if(tec->tec_FirstPixel > 0)
  1400.                 {
  1401.                     totalChars = TE_RoundedTextFit(tec,(STRPTR)string,len,tec->tec_FirstPixel,&delta);
  1402.                     if(totalChars > 0)
  1403.                     {
  1404.                         string += totalChars;
  1405.                         len -= totalChars;
  1406.                         cursorX -= totalChars;
  1407.                     }
  1408.                 }
  1409.                 else
  1410.                 {
  1411.                     delta = 0;
  1412.                 }
  1413.  
  1414.                 if(cursorX >= 0)
  1415.                 {
  1416.                     LONG cursorWidth;
  1417.                     LONG cursorLeft;
  1418.  
  1419.                     cursorLeft = TE_TextLength(tec,string,cursorX) + delta;
  1420.  
  1421.                     if(cursorX < len)
  1422.                         cursorWidth = TE_TextLength(tec,&string[cursorX],1);
  1423.                     else
  1424.                         cursorWidth = tec->tec_CharWidth;
  1425.  
  1426.                     if(cursorLeft + cursorWidth > tec->tec_Width)
  1427.                         cursorWidth = tec->tec_Width - cursorLeft;
  1428.  
  1429.                     if(cursorWidth > 0)
  1430.                     {
  1431.                         LONG cursorTop;
  1432.  
  1433.                         cursorTop = (tec->tec_CursorY - tec->tec_FirstLine) * tec->tec_CharHeight;
  1434.  
  1435.                         if(mode == DRAWCURSOR_Toggle)
  1436.                             TE_SetABPenDrMd(tec,0xFF,OLD_BgPen,COMPLEMENT | JAM1);
  1437.                         else
  1438.                             TE_SetABPenDrMd(tec,0x00,OLD_BgPen,JAM2);
  1439.  
  1440.                         TE_SetWriteMask(tec,0xFF);
  1441.  
  1442.                         TE_FillArea(tec,tec->tec_Left + cursorLeft,tec->tec_Top + cursorTop,cursorWidth,tec->tec_CharHeight);
  1443.  
  1444.                         TE_SetABPenDrMd(tec,tec->tec_TextPen,OLD_BgPen,JAM2);
  1445.                         TE_SetWriteMask(tec,tec->tec_TextPen | tec->tec_BackPen);
  1446.                     }
  1447.                 }
  1448.             }
  1449.         }
  1450.     }
  1451. }
  1452.  
  1453. STATIC VOID
  1454. TE_ShowCursor(struct TextEditContext * tec)
  1455. {
  1456.     if(tec->tec_CursorVisible > 0)
  1457.     {
  1458.         tec->tec_CursorVisible--;
  1459.  
  1460.         if(tec->tec_CursorVisible == VISIBLE)
  1461.             TE_DrawCursor(tec,DRAWCURSOR_Toggle);
  1462.     }
  1463. }
  1464.  
  1465. STATIC VOID
  1466. TE_HideCursor(struct TextEditContext * tec)
  1467. {
  1468.     if(tec->tec_CursorVisible == VISIBLE)
  1469.         TE_DrawCursor(tec,DRAWCURSOR_Toggle);
  1470.  
  1471.     tec->tec_CursorVisible++;
  1472. }
  1473.  
  1474. STATIC VOID
  1475. TE_EraseCursor(struct TextEditContext * tec)
  1476. {
  1477.     TE_DrawCursor(tec,DRAWCURSOR_Erase);
  1478.  
  1479.     tec->tec_CursorVisible++;
  1480. }
  1481.  
  1482. STATIC BOOL
  1483. TE_ChooseVisibleOffsetForCursor(struct TextEditContext * tec)
  1484. {
  1485.     LONG firstPixel = tec->tec_FirstPixel;
  1486.     LONG firstLine = tec->tec_FirstLine;
  1487.     STRPTR string;
  1488.     BOOL modified;
  1489.  
  1490.     if(tec->tec_CursorY < firstLine)
  1491.         firstLine = tec->tec_CursorY;
  1492.     else if (tec->tec_CursorY+1 >= firstLine + tec->tec_NumLines)
  1493.         firstLine = tec->tec_CursorY+1 - tec->tec_NumLines;
  1494.  
  1495.     string = TE_FindLine(tec,tec->tec_CursorY);
  1496.     if(string != NULL)
  1497.     {
  1498.         LONG cursorLeft;
  1499.  
  1500.         cursorLeft = TE_TextLength(tec,string,tec->tec_CursorX);
  1501.         if(cursorLeft < firstPixel)
  1502.             firstPixel = cursorLeft;
  1503.         else if (cursorLeft + tec->tec_CharWidth >= firstPixel + tec->tec_Width)
  1504.             firstPixel = cursorLeft + tec->tec_CharWidth - tec->tec_Width;
  1505.     }
  1506.  
  1507.     if(firstPixel != tec->tec_FirstPixel || firstLine != tec->tec_FirstLine)
  1508.     {
  1509.         tec->tec_FirstPixel    = firstPixel;
  1510.         tec->tec_FirstLine    = firstLine;
  1511.  
  1512.         modified = TRUE;
  1513.     }
  1514.     else
  1515.     {
  1516.         modified = FALSE;
  1517.     }
  1518.  
  1519.     return(modified);
  1520. }
  1521.  
  1522. STATIC VOID
  1523. TE_MakeCursorVisible(struct TextEditContext * tec)
  1524. {
  1525.     BOOL mustRedraw;
  1526.  
  1527.     TE_HideCursor(tec);
  1528.  
  1529.     mustRedraw = TE_ChooseVisibleOffsetForCursor(tec);
  1530.     if(mustRedraw)
  1531.         TE_MarkForRedraw(tec,STARTLINE_First,STOPLINE_Last);
  1532.  
  1533.     TE_ShowCursor(tec);
  1534. }
  1535.  
  1536. /******************************************************************************/
  1537.  
  1538. STATIC VOID
  1539. TE_ValidateCursorX(struct TextEditContext * tec)
  1540. {
  1541.     STRPTR string;
  1542.  
  1543.     string = TE_FindLine(tec,tec->tec_CursorY);
  1544.     if(string != NULL)
  1545.     {
  1546.         LONG cursorX = 0;
  1547.  
  1548.         while(cursorX < tec->tec_CursorX && (*string) != '\0' && (*string) != '\n')
  1549.         {
  1550.             cursorX++;
  1551.             string++;
  1552.         }
  1553.  
  1554.         TE_HideCursor(tec);
  1555.  
  1556.         tec->tec_CursorX = cursorX;
  1557.  
  1558.         TE_ShowCursor(tec);
  1559.     }
  1560. }
  1561.  
  1562. /******************************************************************************/
  1563.  
  1564. VOID
  1565. TE_CursorFirstLine(struct TextEditContext * tec)
  1566. {
  1567.     if(tec->tec_CursorY != 0)
  1568.     {
  1569.         TE_HideCursor(tec);
  1570.  
  1571.         tec->tec_CursorY = 0;
  1572.         TE_ValidateCursorX(tec);
  1573.         TE_MakeCursorVisible(tec);
  1574.  
  1575.         TE_ShowCursor(tec);
  1576.     }
  1577. }
  1578.  
  1579. VOID
  1580. TE_CursorLastLine(struct TextEditContext * tec)
  1581. {
  1582.     LONG cursorY;
  1583.  
  1584.     cursorY = tec->tec_MaxLines-1;
  1585.     if(cursorY < 0)
  1586.         cursorY = 0;
  1587.  
  1588.     if(tec->tec_CursorY != cursorY)
  1589.     {
  1590.         TE_HideCursor(tec);
  1591.  
  1592.         tec->tec_CursorY = cursorY;
  1593.         TE_ValidateCursorX(tec);
  1594.         TE_MakeCursorVisible(tec);
  1595.  
  1596.         TE_ShowCursor(tec);
  1597.     }
  1598. }
  1599.  
  1600. /******************************************************************************/
  1601.  
  1602. VOID
  1603. TE_CursorStartOfLine(struct TextEditContext * tec)
  1604. {
  1605.     if(tec->tec_CursorX != 0)
  1606.     {
  1607.         TE_HideCursor(tec);
  1608.  
  1609.         tec->tec_CursorX = 0;
  1610.         TE_MakeCursorVisible(tec);
  1611.  
  1612.         TE_ShowCursor(tec);
  1613.     }
  1614. }
  1615.  
  1616. VOID
  1617. TE_CursorEndOfLine(struct TextEditContext * tec)
  1618. {
  1619.     STRPTR string;
  1620.  
  1621.     string = TE_FindLine(tec,tec->tec_CursorY);
  1622.     if(string != NULL)
  1623.     {
  1624.         LONG cursorX = 0;
  1625.  
  1626.         while((*string) != '\0' && (*string) != '\n')
  1627.         {
  1628.             cursorX++;
  1629.             string++;
  1630.         }
  1631.  
  1632.         if(tec->tec_CursorX != cursorX)
  1633.         {
  1634.             TE_HideCursor(tec);
  1635.  
  1636.             tec->tec_CursorX = cursorX;
  1637.             TE_MakeCursorVisible(tec);
  1638.  
  1639.             TE_ShowCursor(tec);
  1640.         }
  1641.     }
  1642. }
  1643.  
  1644. /******************************************************************************/
  1645.  
  1646. VOID
  1647. TE_CursorPageUp(struct TextEditContext * tec)
  1648. {
  1649.     LONG numLines;
  1650.  
  1651.     if((tec->tec_CursorY - tec->tec_FirstLine) == 0)
  1652.         numLines = tec->tec_NumLines-1;
  1653.     else
  1654.         numLines = (tec->tec_CursorY - tec->tec_FirstLine);
  1655.  
  1656.     TE_CursorUp(tec,max(1,numLines));
  1657. }
  1658.  
  1659. VOID
  1660. TE_CursorPageDown(struct TextEditContext * tec)
  1661. {
  1662.     LONG numLines;
  1663.  
  1664.     if(tec->tec_CursorY == tec->tec_FirstLine + tec->tec_NumLines-1)
  1665.         numLines = tec->tec_NumLines-1;
  1666.     else
  1667.         numLines = tec->tec_NumLines-1 - (tec->tec_CursorY - tec->tec_FirstLine);
  1668.  
  1669.     TE_CursorDown(tec,max(1,numLines));
  1670. }
  1671.  
  1672. /******************************************************************************/
  1673.  
  1674. VOID
  1675. TE_CursorUp(
  1676.     struct TextEditContext *    tec,
  1677.     LONG                        numLines)
  1678. {
  1679.     if(numLines > 0)
  1680.     {
  1681.         if(numLines < tec->tec_CursorY)
  1682.         {
  1683.             TE_HideCursor(tec);
  1684.  
  1685.             tec->tec_CursorY = tec->tec_CursorY - numLines;
  1686.             TE_ValidateCursorX(tec);
  1687.             TE_MakeCursorVisible(tec);
  1688.  
  1689.             TE_ShowCursor(tec);
  1690.         }
  1691.         else
  1692.         {
  1693.             TE_CursorFirstLine(tec);
  1694.         }
  1695.     }
  1696. }
  1697.  
  1698. VOID
  1699. TE_CursorDown(
  1700.     struct TextEditContext *    tec,
  1701.     LONG                        numLines)
  1702. {
  1703.     if(numLines > 0)
  1704.     {
  1705.         if(tec->tec_CursorY + numLines < tec->tec_MaxLines)
  1706.         {
  1707.             TE_HideCursor(tec);
  1708.  
  1709.             tec->tec_CursorY = tec->tec_CursorY + numLines;
  1710.             TE_ValidateCursorX(tec);
  1711.             TE_MakeCursorVisible(tec);
  1712.  
  1713.             TE_ShowCursor(tec);
  1714.         }
  1715.         else
  1716.         {
  1717.             TE_CursorLastLine(tec);
  1718.         }
  1719.     }
  1720. }
  1721.  
  1722. VOID
  1723. TE_CursorLeft(
  1724.     struct TextEditContext *    tec,
  1725.     LONG                        numColumns)
  1726. {
  1727.     if(numColumns > 0)
  1728.     {
  1729.         STRPTR string;
  1730.  
  1731.         if(numColumns == 1 && tec->tec_CursorX == 0)
  1732.         {
  1733.             if(tec->tec_CursorY > 0)
  1734.             {
  1735.                 string = TE_FindLine(tec,tec->tec_CursorY - 1);
  1736.                 if(string != NULL)
  1737.                 {
  1738.                     TE_HideCursor(tec);
  1739.  
  1740.                     tec->tec_CursorX = TE_StrLen(string);
  1741.                     tec->tec_CursorY = tec->tec_CursorY - 1;
  1742.                     TE_MakeCursorVisible(tec);
  1743.  
  1744.                     TE_ShowCursor(tec);
  1745.                 }
  1746.             }
  1747.         }
  1748.         else
  1749.         {
  1750.             string = TE_FindLine(tec,tec->tec_CursorY);
  1751.             if(string != NULL)
  1752.             {
  1753.                 LONG cursorX = 0;
  1754.  
  1755.                 while(cursorX < tec->tec_CursorX && (*string) != '\0' && (*string) != '\n')
  1756.                 {
  1757.                     cursorX++;
  1758.                     string++;
  1759.                 }
  1760.  
  1761.                 while(numColumns > 0 && cursorX > 0)
  1762.                 {
  1763.                     numColumns--;
  1764.                     cursorX--;
  1765.                 }
  1766.  
  1767.                 if(tec->tec_CursorX != cursorX)
  1768.                 {
  1769.                     TE_HideCursor(tec);
  1770.  
  1771.                     tec->tec_CursorX = cursorX;
  1772.                     TE_MakeCursorVisible(tec);
  1773.  
  1774.                     TE_ShowCursor(tec);
  1775.                 }
  1776.             }
  1777.         }
  1778.     }
  1779. }
  1780.  
  1781. VOID
  1782. TE_CursorRight(
  1783.     struct TextEditContext *    tec,
  1784.     LONG                        numColumns)
  1785. {
  1786.     if(numColumns > 0)
  1787.     {
  1788.         STRPTR string;
  1789.  
  1790.         string = TE_FindLine(tec,tec->tec_CursorY);
  1791.         if(string != NULL)
  1792.         {
  1793.             if(numColumns == 1 && tec->tec_CursorX == TE_StrLen(string))
  1794.             {
  1795.                 if(tec->tec_CursorY + 1 < tec->tec_MaxLines)
  1796.                 {
  1797.                     TE_HideCursor(tec);
  1798.  
  1799.                     tec->tec_CursorX = 0;
  1800.                     tec->tec_CursorY = tec->tec_CursorY + 1;
  1801.                     TE_MakeCursorVisible(tec);
  1802.  
  1803.                     TE_ShowCursor(tec);
  1804.                 }
  1805.             }
  1806.             else
  1807.             {
  1808.                 LONG cursorX = 0;
  1809.  
  1810.                 while(cursorX < tec->tec_CursorX && (*string) != '\0' && (*string) != '\n')
  1811.                 {
  1812.                     cursorX++;
  1813.                     string++;
  1814.                 }
  1815.  
  1816.                 while(numColumns > 0 && (*string) != '\0' && (*string) != '\n')
  1817.                 {
  1818.                     numColumns--;
  1819.                     cursorX++;
  1820.                     string++;
  1821.                 }
  1822.  
  1823.                 if(tec->tec_CursorX != cursorX)
  1824.                 {
  1825.                     TE_HideCursor(tec);
  1826.  
  1827.                     tec->tec_CursorX = cursorX;
  1828.                     TE_MakeCursorVisible(tec);
  1829.  
  1830.                     TE_ShowCursor(tec);
  1831.                 }
  1832.             }
  1833.         }
  1834.     }
  1835. }
  1836.  
  1837. /******************************************************************************/
  1838.  
  1839. VOID
  1840. TE_CursorToMouse(
  1841.     struct TextEditContext *    tec,
  1842.     LONG                        left,
  1843.     LONG                        top)
  1844. {
  1845.     STRPTR string;
  1846.     LONG y;
  1847.  
  1848.     if(left < 0)
  1849.         left = 0;
  1850.     else if (left >= tec->tec_Width)
  1851.         left = tec->tec_Width-1;
  1852.  
  1853.     if(top < 0)
  1854.         top = 0;
  1855.     else if ((top / tec->tec_CharHeight) >= tec->tec_NumLines)
  1856.         top = (tec->tec_NumLines * tec->tec_CharHeight)-1;
  1857.  
  1858.     y = tec->tec_FirstLine + (top / tec->tec_CharHeight);
  1859.     if(y >= tec->tec_MaxLines)
  1860.     {
  1861.         y = tec->tec_MaxLines-1;
  1862.         if(y < 0)
  1863.             y = 0;
  1864.     }
  1865.  
  1866.     string = TE_FindLine(tec,y);
  1867.     if(string != NULL)
  1868.     {
  1869.         LONG x;
  1870.  
  1871.         x = TE_TextFit(tec,string,TE_StrLen(string),tec->tec_FirstPixel + left);
  1872.  
  1873.         if(tec->tec_CursorX != x || tec->tec_CursorY != y)
  1874.         {
  1875.             TE_HideCursor(tec);
  1876.  
  1877.             tec->tec_CursorX = x;
  1878.             tec->tec_CursorY = y;
  1879.  
  1880.             TE_ShowCursor(tec);
  1881.         }
  1882.     }
  1883. }
  1884.  
  1885. VOID
  1886. TE_MoveCursorWithMouse(
  1887.     struct TextEditContext *    tec,
  1888.     LONG                        left,
  1889.     LONG                        top)
  1890. {
  1891.     LONG firstPixel = tec->tec_FirstPixel;
  1892.     LONG firstLine = tec->tec_FirstLine;
  1893.     BOOL cursorHidden;
  1894.  
  1895.     if(left < 0 && firstPixel > 0)
  1896.     {
  1897.         if(firstPixel < tec->tec_CharWidth)
  1898.             firstPixel = 0;
  1899.         else
  1900.             firstPixel -= tec->tec_CharWidth;
  1901.     }
  1902.     else if (left >= tec->tec_Width && firstPixel + tec->tec_Width < (tec->tec_MaxPixels + tec->tec_CharWidth))
  1903.     {
  1904.         if(firstPixel + tec->tec_CharWidth + tec->tec_Width > (tec->tec_MaxPixels + tec->tec_CharWidth))
  1905.         {
  1906.             firstPixel = (tec->tec_MaxPixels + tec->tec_CharWidth) - (tec->tec_CharWidth + tec->tec_Width);
  1907.             if(firstPixel < 0)
  1908.                 firstPixel = 0;
  1909.         }
  1910.         else
  1911.         {
  1912.             firstPixel += tec->tec_CharWidth;
  1913.         }
  1914.     }
  1915.  
  1916.     if(top < 0 && firstLine > 0)
  1917.     {
  1918.         firstLine--;
  1919.     }
  1920.     else if ((top / tec->tec_CharHeight) >= tec->tec_NumLines && firstLine + 1 + tec->tec_NumLines < (tec->tec_MaxLines + 1))
  1921.     {
  1922.         if(firstLine + 1 + tec->tec_NumLines > (tec->tec_MaxLines + 1))
  1923.         {
  1924.             firstLine = (tec->tec_MaxLines + 1) - (1 + tec->tec_NumLines);
  1925.             if(firstLine < 0)
  1926.                 firstLine = 0;
  1927.         }
  1928.         else
  1929.         {
  1930.             firstLine++;
  1931.         }
  1932.     }
  1933.  
  1934.     if(tec->tec_FirstPixel != firstPixel || tec->tec_FirstLine != firstLine)
  1935.     {
  1936.         TE_HideCursor(tec);
  1937.  
  1938.         tec->tec_FirstPixel    = firstPixel;
  1939.         tec->tec_FirstLine    = firstLine;
  1940.  
  1941.         TE_DrawComplete(tec,STARTLINE_First,STOPLINE_Last);
  1942.  
  1943.         cursorHidden = TRUE;
  1944.     }
  1945.     else
  1946.     {
  1947.         cursorHidden = FALSE;
  1948.     }
  1949.  
  1950.     TE_CursorToMouse(tec,left,top);
  1951.  
  1952.     if(cursorHidden)
  1953.         TE_ShowCursor(tec);
  1954. }
  1955.  
  1956. /******************************************************************************/
  1957.  
  1958. BOOL
  1959. TE_MouseInArea(
  1960.     struct TextEditContext *    tec,
  1961.     LONG                        left,
  1962.     LONG                        top)
  1963. {
  1964.     BOOL inArea;
  1965.  
  1966.     inArea = (BOOL)(left >= 0 && left < tec->tec_Width &&
  1967.                     top  >= 0 && top  < tec->tec_Height);
  1968.  
  1969.     return(inArea);
  1970. }
  1971.  
  1972. VOID
  1973. TE_AdjustLeftTop(
  1974.     struct TextEditContext *    tec,
  1975.     LONG *                        leftPtr,
  1976.     LONG *                        topPtr)
  1977. {
  1978.     (*leftPtr)    -= tec->tec_Left;
  1979.     (*topPtr)    -= tec->tec_Top;
  1980. }
  1981.  
  1982. /******************************************************************************/
  1983.  
  1984. BOOL
  1985. TE_IsRedrawNecessary(struct TextEditContext * tec)
  1986. {
  1987.     BOOL result;
  1988.  
  1989.     result = tec->tec_MustRedraw;
  1990.  
  1991.     return(result);
  1992. }
  1993.  
  1994. VOID
  1995. TE_RedrawIfNecessary(struct TextEditContext * tec)
  1996. {
  1997.     if(tec->tec_MustRedraw)
  1998.         TE_DrawComplete(tec,tec->tec_RedrawStartLine,tec->tec_RedrawStopLine);
  1999. }
  2000.  
  2001. STATIC VOID
  2002. TE_MarkForRedraw(
  2003.     struct TextEditContext *    tec,
  2004.     LONG                        startLine,
  2005.     LONG                        stopLine)
  2006. {
  2007.     tec->tec_MustRedraw = TRUE;
  2008.  
  2009.     if(startLine == STARTLINE_First)
  2010.         startLine = 0;
  2011.  
  2012.     if(stopLine == STOPLINE_Last)
  2013.         stopLine = tec->tec_NumLines-1;
  2014.  
  2015.     if(tec->tec_RedrawStartLine > startLine)
  2016.         tec->tec_RedrawStartLine = startLine;
  2017.  
  2018.     if(tec->tec_RedrawStopLine < stopLine)
  2019.         tec->tec_RedrawStopLine = stopLine;
  2020. }
  2021.  
  2022. VOID
  2023. TE_Refresh(struct TextEditContext * tec)
  2024. {
  2025.     TE_EraseCursor(tec); /* == TE_HideCursor(tec) */
  2026.  
  2027.     TE_DrawComplete(tec,STARTLINE_First,STOPLINE_Last);
  2028.  
  2029.     TE_ShowCursor(tec);
  2030. }
  2031.  
  2032. /******************************************************************************/
  2033.  
  2034. VOID
  2035. TE_Activate(struct TextEditContext * tec)
  2036. {
  2037.     if(NOT tec->tec_IsActive)
  2038.     {
  2039.         tec->tec_IsActive = TRUE;
  2040.  
  2041.         tec->tec_TextPen = tec->tec_ActiveTextPen;
  2042.         tec->tec_BackPen = tec->tec_ActiveBackPen;
  2043.  
  2044.         TE_ShowCursor(tec);
  2045.  
  2046.         TE_Refresh(tec);
  2047.  
  2048.         TE_MakeBackup(tec);
  2049.     }
  2050. }
  2051.  
  2052. VOID
  2053. TE_Deactivate(struct TextEditContext * tec)
  2054. {
  2055.     if(tec->tec_IsActive)
  2056.     {
  2057.         TE_HideCursor(tec);
  2058.  
  2059.         tec->tec_IsActive = FALSE;
  2060.  
  2061.         tec->tec_TextPen = tec->tec_InactiveTextPen;
  2062.         tec->tec_BackPen = tec->tec_InactiveBackPen;
  2063.  
  2064.         TE_Refresh(tec);
  2065.     }
  2066. }
  2067.  
  2068. VOID
  2069. TE_InitialRefresh(struct TextEditContext * tec)
  2070. {
  2071.     if(tec->tec_IsActive)
  2072.     {
  2073.         tec->tec_TextPen = tec->tec_ActiveTextPen;
  2074.         tec->tec_BackPen = tec->tec_ActiveBackPen;
  2075.     }
  2076.     else
  2077.     {
  2078.         tec->tec_TextPen = tec->tec_InactiveTextPen;
  2079.         tec->tec_BackPen = tec->tec_InactiveBackPen;
  2080.     }
  2081.  
  2082.     TE_Refresh(tec);
  2083. }
  2084.  
  2085. /******************************************************************************/
  2086.  
  2087. VOID
  2088. TE_DrawDisabled(struct TextEditContext * tec)
  2089. {
  2090.     if(tec->tec_IsDrawable)
  2091.     {
  2092.         STATIC UWORD Ghosting[2] = { 0x4444,0x1111 };
  2093.  
  2094.         TE_SetABPenDrMd(tec,tec->tec_ShadowPen,OLD_BgPen,JAM1);
  2095.  
  2096.         SetAfPt(tec->tec_RastPort,Ghosting,1);
  2097.         TE_FillArea(tec,tec->tec_Left,tec->tec_Top,tec->tec_Width,tec->tec_Height);
  2098.         SetAfPt(tec->tec_RastPort,NULL,0);
  2099.  
  2100.         TE_SetABPenDrMd(tec,tec->tec_TextPen,OLD_BgPen,JAM2);
  2101.     }
  2102. }
  2103.  
  2104. /******************************************************************************/
  2105.  
  2106. #endif /* DO_TEXTEDIT_KIND */
  2107.